#pragma once
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define ERROR_MESSAGE(NAME) \
    {                       \
        perror(NAME);       \
        exit(1);            \
    }
#define FIFO_PATH "./"
#define FIFO_NAME "sharedfile"
#define FIFO_PATHNAME "./sharedfile"

namespace My_Shared_Memory
{
    class SharedMemory
    {
    public:
        // 构造
        SharedMemory(const char *pathname, int size, int shmflg)
            : _pathname(pathname), _size(size), _shmflg(shmflg)
        {
            // 获得KEY
            key_t mykey = ftok(_pathname, 'A');
            if (mykey <= 0)
            {
                ERROR_MESSAGE("ftok");
            }

            // 创建共享内存
            umask(0);
            _myshmid = shmget(mykey, _size, _shmflg);
            if (_myshmid == -1)
            {
                ERROR_MESSAGE("shmget");
            }
            // 附加共享内存
            _newshared = (int *)shmat(_myshmid, nullptr, 0);
            if (_newshared == (int *)-1)
            {
                ERROR_MESSAGE("shmat");
            }
        }
        // 拷贝构造
        SharedMemory(const SharedMemory &cpy) = delete;
        //
        SharedMemory operator=(const SharedMemory &cpy) = delete;

        // 析构
        ~SharedMemory()
        {
            // 共享内存分离
            shmdt(_newshared);
            std::cout << "析构" << std::endl;

            if (_shmflg != IPC_CREAT)
            {
                // 共享内存删除
                std::cout << "删除" << std::endl;

                int ctlret = shmctl(_myshmid, IPC_RMID, nullptr);
                if (ctlret == -1)
                {
                    ERROR_MESSAGE("shmctl");
                }
            }
        }

        void *Get()
        {
            return _newshared;
        }

    private:
        const char *_pathname;
        int _size;
        int _shmflg;
        int _myshmid;
        void *_newshared;
    };
}